<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>面向对象</title>
</head>

<body>
    <script src="./idnex.js"></script>
    <!-- 
        面向对象：万物皆对象
            1.函数的作用：
                封装代码 方便代码调用和管理；
                用来生成对象；
            2.构造函数：
                对象都是由函数创造的，创造对象的函数就叫做构造函数；
                任何数据类型都是由构造函数生成的(undefined,null除外，这是由开发JS的语言规定的)
                
                构造函数和普通函数的区别：
                    函数名不一样，构造函数名首字目大写；(这是一种约定)
                    使用方式不一样，构造函数使用 new 操作符生成对象实例；
            3.对象的生成方式：
                let obj = new Object() 构造函数
                let obj = {} 语法糖 字面量创造
            4.构造函数的格式
                function Foo(){} 或者 let Foo = function (){}
                箭头函数不能当做构造函数,因为它没有this指向；
            5.构造函数在生成对象的时候，对对象进行一些设置，可以通过this来控制实例对象的属性特点；
                function Foo(){
                    this.a = 1
                } 
                let obj = new Foo()
                obj.a = 1
            6.什么是对象的基因：
                任何对象都有一条隐式属性：__proto__ 这就是对象的基因，也就是隐式原型；
                该基因当中蕴含的一些方法，就可以被继承；
            7.隐式原型从哪里来?
                隐式原型中含有一个属性 constructor 构造器，表明该实例的构造者是谁；

                任何函数都有一条属性：.prototype 即函数的原型 基因库 可以传递给它的实例对象；
                Foo.prototype === obj.__porto__

                修改构造函数的prototype属性，会对其所有实例对象产生影响；
            8.对象是怎么访问属性？
                (1).首先看对象内部有没有该属性；
                (2).如果没有，就去原型中寻找；

            9.真数组和类数组：
                真数组是有 Array构造函数实例出来的才是真数组；
                类数组：本质上是由非Array的其他对象实例出来的；
                因此类数组不具备Array的基因库，无法使用真数组的方法；

                可以通过扩展运算符将类数组转化为真数组：
                    [...NodeList]
                    这样就可以使用真数组的方法了；
            作业：自行封装一个 new 方法；
            
            10.Foo.prototype 和 Foo.__proto__ 的区别：
                前者是作为Foo自身的基因库，向下传递的存在；
                后者是Foo作为对象，由其父级(Function)的prototype继承而来；

            11.原型开发的两种形式：
                Object.prototype.fn = function(){}
                    这种方法不会改变对象的原型，而是在原型对象里添加了一个属性；

                Object.prototype = {
                    fn()
                }
                    这种方法是重新用一个对象表示原型，相当于换了个基因，可能会覆盖实例的原型，不推荐使用；
            12.Object、Function、window之间的关系：
                window是最小的，也是一个对象实例
                Function 和 Object：都是构造函数
                    
                    任何对象都是由Object创造的；
                    任何函数都是由Function创造的；
                    
                    Function其实是由Object创建的，只不过，将Function的构造器修改成了Function；
                    为了维持稳定，解决矛盾，所以有了规定：
                        Function是由Function创建的；

                        Function.constructor === Function
                        Function.prototype === Function.__proto__
                        Function.prototype === Object.__proto__

                    Object.prototype 才是基因的源泉；
                    Object.prototype.__proto__ 是万物原型的终点；

                    所以 万物皆对象；
                
            13.原型链：
                对象访问属性，访问不到 就去__proto__找，还找不到就去__proto__.__proto__找...
                以此类推...就形成原型链，终点就是Object.prototype.__proto__

                其实就是，一个对象的原型可以指向另一个对象实例的原型，可以无限嵌套...

            14.鉴别所有数据类型的万能方法：
                调用统一的 toString 方法 返回的数据类型一致；
                Object.prototype.toString.call(数据类型)
            
            15.面向对象思想：编排对象，通过构造者控制；
                实际上就是让开发 变成指令式开发；

            16.class: 关键词 一个面向对象编程的语法糖 保证了代码的完整性 ES6的写法
                相当于整了一个叫 Foo 的构造函数
                class Foo ==> function Foo
                constructor ==> (){}
                
                class Foo{
                    constructor(x){
                        this.a = x
                    }
                }

                class的继承：
                    使用extends关键字 实现继承
                    在constructor当中 必须有一个 super() 代表在子类中添加父类的属性

                    如果子类当中有父类的同名属性 则优先使用子类的；

                class的静态的方法：
                    方法前面可添加 static

                    class Foo{
                        static fn(){
                            ...
                        }
                    }
                    Foo.fn()

                    只能由构造函数直接访问 不能由其实例执行

                    静态方法当中无法直接使用this 因为其指向并不是实例对象；

                    作用：一般对构造函数初始化的时候进行一些修饰；

     -->
</body>

</html>